import React, { FunctionComponent } from 'react';
import { graphql, useFragment } from 'react-relay';
import { Field, Form, Formik } from 'formik';
import * as Yup from 'yup';
import { FormikConfig } from 'formik/dist/types';
import { GenericContext } from '@components/common/model/GenericContextModel';
import {
  malwareAnalysisEditionOverviewFocus,
  malwareAnalysisMutationRelationAdd,
  malwareAnalysisMutationRelationDelete,
} from '@components/analyses/malware_analyses/MalwareAnalysisEditionOverview';
import TextField from '../../../../components/TextField';
import { ExternalReferencesValues } from '../../common/form/ExternalReferencesField';
import { SubscriptionFocus } from '../../../../components/Subscription';
import CommitMessage from '../../common/form/CommitMessage';
import { adaptFieldValue } from '../../../../utils/String';
import { isNone, useFormatter } from '../../../../components/i18n';
import { Option } from '../../common/form/ReferenceField';
import { MalwareAnalysisEditionDetails_malwareAnalysis$key } from './__generated__/MalwareAnalysisEditionDetails_malwareAnalysis.graphql';
import { MalwareAnalysisEditionDetailsFocusMutation } from './__generated__/MalwareAnalysisEditionDetailsFocusMutation.graphql';
import DateTimePickerField from '../../../../components/DateTimePickerField';
import { useSchemaEditionValidation } from '../../../../utils/hooks/useEntitySettings';
import { RelayError } from '../../../../relay/relayTypes';
import { MESSAGING$ } from '../../../../relay/environment';
import useFormEditor, { GenericData } from '../../../../utils/hooks/useFormEditor';
import AlertConfidenceForEntity from '../../../../components/AlertConfidenceForEntity';
import useApiMutation from '../../../../utils/hooks/useApiMutation';
import { parse } from '../../../../utils/Time';

const malwareAnalysisMutationFieldPatch = graphql`
    mutation MalwareAnalysisEditionDetailsFieldPatchMutation(
        $id: ID!
        $input: [EditInput]!
        $commitMessage: String
        $references: [String]
    ) {
        malwareAnalysisFieldPatch(id: $id, input: $input, commitMessage: $commitMessage, references: $references){
            ...MalwareAnalysisEditionDetails_malwareAnalysis
            ...MalwareAnalysis_malwareAnalysis
        }

    }
`;

export const malwareAnalysisEditionDetailsFocus = graphql`
    mutation MalwareAnalysisEditionDetailsFocusMutation($id: ID!, $input: EditContext!) {
        malwareAnalysisContextPatch(id: $id,  input: $input) {
            id
        }
    }
`;

export const malwareAnalysisEditionDetailsFragment = graphql`
    fragment MalwareAnalysisEditionDetails_malwareAnalysis on MalwareAnalysis {
        id
        configuration_version
        analysis_started
        analysis_ended
        analysis_engine_version
        analysis_definition_version
        modules
        confidence
        entity_type
        objectMarking {
          id
          definition_type
          definition
          x_opencti_order
          x_opencti_color
        }
    }
`;
interface MalwareAnalysisEditionDetailsProps {
  malwareAnalysisRef: MalwareAnalysisEditionDetails_malwareAnalysis$key,
  context?: readonly (GenericContext | null)[] | null;
  enableReferences?: boolean
  handleClose: () => void
}

interface MalwareAnalysisEditionFormValues {
  message?: string
  references: ExternalReferencesValues | undefined
  configuration_version?: string
  modules?: string
  analysis_started?: Option
  analysis_ended?: Option
}

// eslint-disable-next-line max-len
const MalwareAnalysisEditionDetails: FunctionComponent<MalwareAnalysisEditionDetailsProps> = ({ malwareAnalysisRef, context, enableReferences = false, handleClose }) => {
  const { t_i18n } = useFormatter();
  const basicShape = {
    configuration_version: Yup.string().nullable(),
    analysis_started: Yup.date().nullable()
      .typeError(t_i18n('The value must be a datetime (yyyy-MM-dd hh:mm (a|p)m)')),
    analysis_ended: Yup.date().nullable()
      .typeError(t_i18n('The value must be a datetime (yyyy-MM-dd hh:mm (a|p)m)')),
    analysis_engine_version: Yup.string().nullable(),
    analysis_definition_version: Yup.string().nullable(),
    modules: Yup.string().nullable(),
  };
  const malwareAnalysisDetailsValidator = useSchemaEditionValidation('Malware-Analysis', basicShape);
  const malwareAnalysis = useFragment(malwareAnalysisEditionDetailsFragment, malwareAnalysisRef);
  const [commitEditionDetailsFocus] = useApiMutation<MalwareAnalysisEditionDetailsFocusMutation>(malwareAnalysisEditionDetailsFocus);

  const queries = {
    fieldPatch: malwareAnalysisMutationFieldPatch,
    relationAdd: malwareAnalysisMutationRelationAdd,
    relationDelete: malwareAnalysisMutationRelationDelete,
    editionFocus: malwareAnalysisEditionOverviewFocus,
  };
  const editor = useFormEditor(
    malwareAnalysis as GenericData,
    enableReferences,
    queries,
    malwareAnalysisDetailsValidator,
  );
  const handleChangeFocus = (name: string) => {
    commitEditionDetailsFocus({
      variables: {
        id: malwareAnalysis.id,
        input: {
          focusOn: name,
        },
      },
    });
  };

  const handleSubmitField = (name: string, value: string) => {
    if (!enableReferences) {
      const finalValue: string = value as string;
      malwareAnalysisDetailsValidator
        .validateAt(name, { [name]: value })
        .then(() => {
          editor.fieldPatch({
            variables: {
              id: malwareAnalysis.id,
              input: [{ key: name, value: [finalValue ?? ''] }],
            },
          });
        })
        .catch(() => false);
    }
  };

  const handleSubmitModules = (name: string, value: string) => {
    if (!enableReferences) {
      const finalValue = value && value.length > 0 ? value.split('\n') : [];
      malwareAnalysisDetailsValidator
        .validateAt(name, { [name]: value })
        .then(() => {
          editor.fieldPatch({
            variables: {
              id: malwareAnalysis.id,
              input: [{ key: name, value: finalValue }],
            },
          });
        })
        .catch(() => false);
    }
  };

  const onSubmit: FormikConfig<MalwareAnalysisEditionFormValues>['onSubmit'] = (values, { setSubmitting }) => {
    const { message, references, ...otherValues } = values;
    const commitMessage = message ?? '';
    const commitReferences = (references ?? []).map(({ value }) => value);

    const inputValues = Object.entries({
      ...otherValues,
      modules: values.modules?.split('\n') ?? [],
      analysis_started: values.analysis_started ? parse(values.analysis_started).format() : null,
      analysis_ended: values.analysis_ended ? parse(values.analysis_ended).format() : null,
    }).map(([key, value]) => ({ key, value: adaptFieldValue(value) }));

    editor.fieldPatch({
      variables: {
        id: malwareAnalysis.id,
        input: inputValues,
        commitMessage: commitMessage.length > 0 ? commitMessage : null,
        references: commitReferences,
      },
      onCompleted: () => {
        setSubmitting(false);
        handleClose();
      },
      onError: (error) => {
        const { errors } = (error as unknown as RelayError).res;
        MESSAGING$.notifyError(errors.at(0)?.data.reason);
        setSubmitting(false);
      },
    });
  };
  const initialValues = {
    configuration_version: malwareAnalysis.configuration_version ?? '',
    analysis_started: !isNone(malwareAnalysis.analysis_started) ? malwareAnalysis.analysis_started : null,
    analysis_ended: !isNone(malwareAnalysis.analysis_ended) ? malwareAnalysis.analysis_ended : null,
    analysis_engine_version: malwareAnalysis.analysis_engine_version,
    analysis_definition_version: malwareAnalysis.analysis_definition_version,
    modules: (malwareAnalysis.modules ?? []).join('\n'),
    references: [],
  };
  return (
    <Formik
      enableReinitialize
      initialValues={initialValues}
      validationSchema={malwareAnalysisDetailsValidator}
      onSubmit={onSubmit}
    >
      {({
        submitForm,
        isSubmitting,
        setFieldValue,
        values,
      }) => (
        <Form style={{ margin: '20px 0 20px 0' }}>
          <AlertConfidenceForEntity entity={malwareAnalysis} />
          <Field
            component={TextField}
            name="configuration_version"
            label={t_i18n('Configuration version')}
            fullWidth
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus context={context} fieldName="configuration_version" />
                        }
          />
          <Field
            component={DateTimePickerField}
            name="analysis_started"
            label={t_i18n('Analysis started')}
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitField}
            textFieldProps={{
              label: t_i18n('Analysis started'),
              variant: 'standard',
              fullWidth: true,
              style: { marginTop: 20 },
              helperText: (
                <SubscriptionFocus context={context} fieldName="analysis_started"/>
              ),
            }}
          />
          <Field
            component={DateTimePickerField}
            name="analysis_ended"
            label={t_i18n('Analysis ended')}
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitField}
            textFieldProps={{
              label: t_i18n('Analysis ended'),
              variant: 'standard',
              fullWidth: true,
              style: { marginTop: 20 },
              helperText: (
                <SubscriptionFocus context={context} fieldName="analysis_ended"/>
              ),
            }}
          />
          <Field
            component={TextField}
            name="analysis_engine_version"
            label={t_i18n('Analysis engine version')}
            style={{ marginTop: 20 }}
            fullWidth
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus context={context} fieldName="analysis_engine_version" />
                      }
          />
          <Field
            component={TextField}
            name="analysis_definition_version"
            label={t_i18n('Analysis definition version')}
            style={{ marginTop: 20 }}
            fullWidth
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus context={context} fieldName="analysis_definition_version" />
                      }
          />
          <Field
            component={TextField}
            name="modules"
            label={t_i18n('Modules (1 / line)')}
            fullWidth
            multiline
            rows="4"
            style={{ marginTop: 20 }}
            onFocus={handleChangeFocus}
            onSubmit={handleSubmitModules}
            helperText={
              <SubscriptionFocus context={context} fieldName="modules" />
                      }
          />
          {enableReferences && (
          <CommitMessage
            submitForm={submitForm}
            disabled={isSubmitting}
            setFieldValue={setFieldValue}
            values={values.references}
            id={malwareAnalysis.id}
            open={false}
          />
          )}
        </Form>
      )}
    </Formik>
  );
};

export default MalwareAnalysisEditionDetails;
